#include "rgb_light.h"
#include "bflb_gpio.h"
#include "bflb_pwm_v2.h"
#include "bflb_mtimer.h"
#include "string.h"
#include "bflb_clock.h"

#define RGB_R GPIO_PIN_12
#define RGB_G GPIO_PIN_14
#define RGB_B GPIO_PIN_15

#define PWM_R PWM_CH0
#define PWM_G PWM_CH2
#define PWM_B PWM_CH3

static struct bflb_device_s* gpio;
static struct bflb_device_s* pwm;

static uint32_t light_status = 0;

void rgb_init()
{
    gpio = bflb_device_get_by_name("gpio");
    pwm = bflb_device_get_by_name("pwm_v2_0");

    bflb_gpio_init(gpio, RGB_R, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, RGB_G, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, RGB_B, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

    struct bflb_pwm_v2_config_s cfg = {
        .clk_source = BFLB_SYSTEM_PBCLK,
        .clk_div = 80,
        .period = 2550,
    };

    bflb_pwm_v2_init(pwm, &cfg);
    bflb_pwm_v2_channel_set_threshold(pwm, PWM_R, 0, 2550);
    bflb_pwm_v2_channel_set_threshold(pwm, PWM_G, 0, 2550);
    bflb_pwm_v2_channel_set_threshold(pwm, PWM_B, 0, 2500);

    bflb_pwm_v2_start(pwm);

}

void rgb_light_off()
{
    if (light_status != 0) {
        light_status = 0;

        //R
        bflb_pwm_v2_channel_negative_stop(pwm, PWM_R);
        bflb_pwm_v2_channel_positive_stop(pwm, PWM_R);
        //G
        bflb_pwm_v2_channel_positive_stop(pwm, PWM_G);
        bflb_pwm_v2_channel_negative_stop(pwm, PWM_G);
        //B
        bflb_pwm_v2_channel_positive_stop(pwm, PWM_B);
        bflb_pwm_v2_channel_negative_stop(pwm, PWM_B);
        bflb_pwm_v2_stop(pwm);
    }
}

void rgb_light_on()
{
    if (light_status != 1)
    {
        light_status = 1;

        bflb_pwm_v2_channel_negative_start(pwm, PWM_R);
        bflb_pwm_v2_channel_positive_start(pwm, PWM_R);

        bflb_pwm_v2_channel_positive_start(pwm, PWM_G);
        bflb_pwm_v2_channel_negative_start(pwm, PWM_G);

        bflb_pwm_v2_channel_positive_start(pwm, PWM_B);
        bflb_pwm_v2_channel_negative_start(pwm, PWM_B);
        bflb_pwm_v2_start(pwm);
    }

}

void rgb_toggle()
{
    if (light_status) {
        rgb_light_off();
    }
    else {
        rgb_light_on();
    }
}

int rgb_status()
{
    return light_status;
}

bool strisdigit(char* str)
{
    if (str == NULL) return false;
    char* ch = str;
    while (ch != NULL && *ch != '\0') {
        if (*ch < '0' || *ch > '9') {
            return false;
        }
        ch++;
    }
    return true;
}

int rgb_update(int r, int g, int b) {

    printf("r: %d, g: %d, b: %d\n", r, g, b);

    bflb_pwm_v2_channel_set_threshold(pwm, PWM_R, 0, r * 10);
    bflb_pwm_v2_channel_set_threshold(pwm, PWM_G, 0, g * 10);
    bflb_pwm_v2_channel_set_threshold(pwm, PWM_B, 0, b * 10);

    if (light_status == 0) {
        rgb_light_on();
    }

}
/**
 * rgb 0xff0000 red
 * rgb 0x00ff00 green
 * rgb 0x0000ff blue
 *
 *
 * 十进制模式.0结尾可以省略
 * rgb 255 red
 * rgb 0.255 green
 * rgb 0.0.255 blue
 *
 * @brief
 * @param  argc
 * @param  argv
 * @return int
 */
int rgb_shell(int argc, const char** argv)
{
    if (argc != 2 || argv[1] == '\0' || strlen(argv[1]) <= 0) {
        printf("Usage:[%s] 0xFF00|255.0.0\n", argv[0]);
        return 0;
    }
    char* color_str = argv[1];
    //转换大小写
    color_str = strupr(color_str);

    if (strncmp(color_str, "0X", 2) == 0) {

        int int_color = strtol(color_str, NULL, 16);
        //16-24bit
        int r = int_color >> 16 & 0xff;
        //9-16bit
        int g = int_color >> 8 & 0xff;
        //1-8bit
        int b = int_color & 0xff;
        rgb_update(r, g, b);
        return 0;
    }

    int array[3] = { -1,0,0 };

    char* token = strtok(color_str, ".");
    int index = 1;
    if (strisdigit(color_str)) {
        array[0] = atoi(color_str);
    }

    while (token != NULL) {
        token = strtok(NULL, ".");
        if (strisdigit(token)) {
            array[index] = atoi(token);
        }
        else {
            break;
        }
        index++;
    }
    for (int i = 0; i < 3;i++) {
        if (array[i] < 0 || array[i] > 255) {
            printf("Usage:[%s] 0xFF00|255.0.0\n", argv[0]);
            return 0;
        }
    }
    rgb_update(array[0], array[1], array[2]);

    return 0;
}

/**
 * @brief 开灯
 * @param  argc
 * @param  argv
 * @return int
 */
int rgb_shell_on(int argc, const char** argv)
{
    rgb_light_on();
    return 0;
}

/**
 * @brief 关灯
 * @param  argc
 * @param  argv
 * @return int
 */
int rgb_shell_off(int argc, const char** argv)
{
    rgb_light_off();
    return 0;
}

//注册rgb_on shell命令
SHELL_CMD_EXPORT_ALIAS(rgb_shell_on, rgb_on, rgb on);
//注册rgb_off shell 命令
SHELL_CMD_EXPORT_ALIAS(rgb_shell_off, rgb_off, rgb off);
//注册rgb 调节 shell 命令
SHELL_CMD_EXPORT_ALIAS(rgb_shell, rgb, rgb_shell);

